#include <tsubamegaeshi-base/parser.h>
#include <cstdio>
#include <boost/regex.hpp>
#include <boost/timer.hpp>
#include <iostream>
#include <functional>

#define BIG_REGEX 1

static void
dummy_callback(const boost::match_results<std::string::const_iterator>& m)
{
  for (int i = 0; i < m.size(); i++) {
    std::cout << i << '[' << m.str(i) << ']' << std::endl;
  }
  std::cout << m.size() << " datas. " << std::endl << std::endl;
}

#if BIG_REGEX


boost::regex all_re(// (time (now 15.78))
                    "\\(time \\(now ([^\\)]+)\\)\\)" "|"
                    // (GS (t 0.00) (pm BeforeKickOff))
                    "\\(GS \\(t ([^\\)]+)\\) \\(pm ([^\\)]+)\\)\\)"  "|"
                    // (GS (unum 11) (team left) (t 0.00) (pm BeforeKickOff))
                    "\\(GS \\(unum ([^\\)]+)\\) \\(team ([^\\)]+)\\) \\(t ([^\\)]+)\\) \\(pm ([^\\)]+)\\)\\)" "|"
                    // (GYR (n torso) (rt -0.02 0.01 0.00))
                    "\\(GYR \\(n ([^\\)]+)\\) \\(rt (\\S+) (\\S+) ([^\\)]+)\\)\\)" "|"
                    // (F1L (pol 10.40 134.99 -17.79)) 
                    "\\((\\w\\w\\w) \\(pol (\\S+) (\\S+) ([^\\)]+)\\)\\)" "|"
                    // (B (pol 10.40 134.99 -17.79)) 
                    "\\(B \\(pol (\\S+) (\\S+) ([^\\)]+)\\)\\)" "|"
                    // (UJ (n laj1_2) (ax1 0.00) (ax2 -0.00))
                    "\\(UJ \\(n ([^\\)]+)\\) \\(ax1 ([^\\)]+)\\) \\(ax2 ([^\\)]+)\\)\\)" "|"
                    // (HJ (n laj3) (ax -0.00))
                    "\\(HJ \\(n ([^\\)]+)\\) \\(ax ([^\\)]+)\\)\\)" "|"
                    // (FRP (n lf) (c -0.08 0.09 -0.05) (f 0.29 -0.34 12.23))
                    "\\(FRP \\(n ([^\\)]+)\\) \\(c (\\S+) (\\S+) ([^\\)]+)\\) \\(f (\\S+) (\\S+) ([^\\)]+)\\)\\)" "|"
                    // (mypos <x> <y> <z>)
                    "\\(mypos (\\S+) (\\S+) ([^\\)]+)\\)" "|"
                    // (P (team tsubame2) (id 1) (pol 36.00 0.03 -0.07))
                    "\\(P \\(team ([^\\)]+)\\) \\(id ([^\\)]+)\\) \\(pol (\\S+) (\\S+) ([^\\)]+)\\)\\)"
                    );
#else
// (time (now 15.78))
boost::regex time_re("\\(time \\(now ([^\\)]+)\\)\\)");
// (GS (t 0.00) (pm BeforeKickOff))
boost::regex gs_re("\\(GS \\(t ([^\\)]+)\\) \\(pm ([^\\)]+)\\)\\)");
// (GS (unum 11) (team left) (t 0.00) (pm BeforeKickOff))
boost::regex gs2_re("\\(GS \\(unum ([^\\)]+)\\) \\(team ([^\\)]+)\\) \\(t ([^\\)]+)\\) \\(pm ([^\\)]+)\\)\\)");
// (GYR (n torso) (rt -0.02 0.01 0.00))
boost::regex gyr_re("\\(GYR \\(n ([^\\)]+)\\) \\(rt (\\S+) (\\S+) ([^\\)]+)\\)\\)");
// (F1L (pol 10.40 134.99 -17.79)) 
boost::regex flag_re("\\((\\w\\w\\w) \\(pol (\\S+) (\\S+) ([^\\)]+)\\)\\)");
// (B (pol 10.40 134.99 -17.79)) 
boost::regex ball_re("\\(B \\(pol (\\S+) (\\S+) ([^\\)]+)\\)\\)");
// (UJ (n laj1_2) (ax1 0.00) (ax2 -0.00))
boost::regex uj_re("\\(UJ \\(n ([^\\)]+)\\) \\(ax1 ([^\\)]+)\\) \\(ax2 ([^\\)]+)\\)\\)");
// (HJ (n laj3) (ax -0.00))
boost::regex hj_re("\\(HJ \\(n ([^\\)]+)\\) \\(ax ([^\\)]+)\\)\\)");
// (FRP (n lf) (c -0.08 0.09 -0.05) (f 0.29 -0.34 12.23))
boost::regex frp_re("\\(FRP \\(n ([^\\)]+)\\) \\(c (\\S+) (\\S+) ([^\\)]+)\\) \\(f (\\S+) (\\S+) ([^\\)]+)\\)\\)");
// (mypos -18.00 9.00 3.55))
boost::regex mypos_re("\\(mypos (\\S+) (\\S+) ([^\\)]+)\\)");
#endif

struct Parser::impl {
#if BIG_REGEX
  struct all_cb_functor {
    Parser* p_;
    all_cb_functor(Parser* p):p_(p){}
    ~all_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      // dummy_callback(m); 
      if      (! m.str( 1).empty() ) { p_->time_callback (m,  1-1); }
      else if (! m.str( 2).empty() ) { p_->gs_callback   (m,  2-1); }
      else if (! m.str( 4).empty() ) { p_->gs_callback   (m,  4-1); }
      else if (! m.str( 8).empty() ) { p_->gyr_callback  (m,  8-1); }
      else if (! m.str(12).empty() ) { p_->flag_callback (m, 12-1); }
      else if (! m.str(16).empty() ) { p_->ball_callback (m, 16-1); }
      else if (! m.str(19).empty() ) { p_->uj_callback   (m, 19-1); }
      else if (! m.str(22).empty() ) { p_->hj_callback   (m, 22-1); }
      else if (! m.str(24).empty() ) { p_->frp_callback  (m, 24-1); }
      else if (! m.str(34).empty() ) { p_->player_callback(m, 34-1); }
      else                           { dummy_callback(m); } 
      return true;
    }
  };
  all_cb_functor all_cb_;

  impl(Parser* p)
  : all_cb_(p)
  {}

#else
  struct time_cb_functor {
    Parser* p_;
    time_cb_functor(Parser* p):p_(p){}
    ~time_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->time_callback(m, 0);
      return true;
    }
  };
  time_cb_functor time_cb_;

  struct gs_cb_functor {
    Parser* p_;
    gs_cb_functor(Parser* p):p_(p){}
    ~gs_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->gs_callback(m, 0);
      return true;
    }
  };
  gs_cb_functor gs_cb_;

  struct gyr_cb_functor {
    Parser* p_;
    gyr_cb_functor(Parser* p):p_(p){}
    ~gyr_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->gyr_callback(m, 0);
      return true;
    }
  };
  gyr_cb_functor gyr_cb_;

  struct flag_cb_functor {
    Parser* p_;
    flag_cb_functor(Parser* p):p_(p){}
    ~flag_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->flag_callback(m, 0);
      return true;
    }
  };
  flag_cb_functor flag_cb_;

  struct ball_cb_functor {
    Parser* p_;
    ball_cb_functor(Parser* p):p_(p){}
    ~ball_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->ball_callback(m, 0);
      return true;
    }
  };
  ball_cb_functor ball_cb_;

  struct uj_cb_functor {
    Parser* p_;
    uj_cb_functor(Parser* p):p_(p){}
    ~uj_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->uj_callback(m, 0);
      return true;
    }
  };

  uj_cb_functor uj_cb_;

  struct hj_cb_functor {
    Parser* p_;
    hj_cb_functor(Parser* p):p_(p){}
    ~hj_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->hj_callback(m, 0);
      return true;
    }
  };
  hj_cb_functor hj_cb_;

  struct frp_cb_functor {
    Parser* p_;
    frp_cb_functor(Parser* p):p_(p){}
    ~frp_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->frp_callback(m, 0);
      return true;
    }
  };
  frp_cb_functor frp_cb_;

  struct mypos_cb_functor {
    Parser* p_;
    mypos_cb_functor(Parser* p):p_(p){}
    ~mypos_cb_functor(){}
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      p_->mypos_callback(m, 0);
      return true;
    }
  };
  mypos_cb_functor mypos_cb_;

  impl(Parser* p)
  : time_cb_(p),
    gs_cb_(p),
    gyr_cb_(p),
    flag_cb_(p),
    ball_cb_(p),
    uj_cb_(p),
    hj_cb_(p),
    frp_cb_(p),
    mypos_cb_(p)
  {}
#endif

  ~impl(){}

  struct test_functor {
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      dummy_callback(m);
      return true;
    }
  };
  struct null_functor {
    bool operator()(const boost::match_results<std::string::const_iterator>& m) {
      return true;
    }
  };


  void
  parse(const std::string& message)
  {
#if BIG_REGEX
//     boost::regex_grep(null_functor(), message, all_re);
    boost::regex_grep(all_cb_, message, all_re);
#else
//     boost::regex_grep(null_functor(), message, time_re);
//     boost::regex_grep(null_functor(), message, gs_re);
//     boost::regex_grep(null_functor(), message, gs2_re);
//     boost::regex_grep(null_functor(), message, gyr_re);
//     boost::regex_grep(null_functor(), message, flag_re);
//     boost::regex_grep(null_functor(), message, ball_re);
//     boost::regex_grep(null_functor(), message, uj_re);
//     boost::regex_grep(null_functor(), message, hj_re);
//     boost::regex_grep(null_functor(), message, frp_re);
//     boost::regex_grep(null_functor(), message, mypos_re);
    boost::regex_grep(time_cb_, message, time_re);
    boost::regex_grep(gs_cb_, message, gs_re);
    boost::regex_grep(gs_cb_, message, gs2_re);
    boost::regex_grep(gyr_cb_, message, gyr_re);
    boost::regex_grep(flag_cb_, message, flag_re);
    boost::regex_grep(ball_cb_, message, ball_re);
    boost::regex_grep(uj_cb_, message, uj_re);
    boost::regex_grep(hj_cb_, message, hj_re);
    boost::regex_grep(frp_cb_, message, frp_re);
    boost::regex_grep(mypos_cb_, message, mypos_re);
#endif
  }

};


Parser::Parser()
  : pimpl_(new impl(this))
{
}

Parser::~Parser()
{
}

void
Parser::parse(const std::string& message)
{
  //puts(message.c_str());

  pimpl_->parse(message);
}


void
Parser::time_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::gs_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::gyr_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::flag_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::ball_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::uj_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::hj_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::frp_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::mypos_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}

void
Parser::player_callback(const boost::match_results<std::string::const_iterator>& m, int i=0)
{
  dummy_callback(m);
}


